<?php

namespace Modules\Common\Exceptions\Base;

use Exception as PHPException;
use Illuminate\Support\Facades\Log;
use Modules\Common\Models\SystemError;
use Modules\Common\Util\Api;
use Modules\Common\Util\System;
use Throwable;


class Exception extends PHPException
{
    const API_CODE = 0;
    const DEBUG = 'debug';
    const INFO = 'info';
    const NOTICE = 'notice';
    const WARNING = 'warning';
    const ERROR = 'error';
    const CRITICAL = 'critical';
    const ALERT = 'alert';
    const EMERGENCY = 'emergency';

    protected $userMessage;
    protected $userMessageData;

    protected $logLevel;
    protected $logDescription;
    protected $logContext;

    public static function new()
    {
        return new static();
    }

    public function throw()
    {
        throw $this;
    }

    public function tellUser($userMessage, $userMessageData = null)
    {
        $this->userMessage = $userMessage;
        $this->userMessageData = $userMessageData;
        return $this;
    }

    public function logDebug($logDescription, $logContext = null)
    {
        return $this->log(self::DEBUG, $logDescription, $logContext);
    }

    public function logInfo($logDescription, $logContext = null)
    {
        return $this->log(self::INFO, $logDescription, $logContext);
    }

    public function logNotice($logDescription, $logContext = null)
    {
        return $this->log(self::NOTICE, $logDescription, $logContext);
    }

    public function logWarning($logDescription, $logContext = null)
    {
        return $this->log(self::WARNING, $logDescription, $logContext);
    }

    public function logError($logDescription, $logContext = null)
    {
        return $this->log(self::ERROR, $logDescription, $logContext);
    }

    public function logCritical($logDescription, $logContext = null)
    {
        return $this->log(self::CRITICAL, $logDescription, $logContext);
    }

    public function logAlert($logDescription, $logContext = null)
    {
        return $this->log(self::ALERT, $logDescription, $logContext);
    }

    public function logEmergency($logDescription, $logContext = null)
    {
        return $this->log(self::EMERGENCY, $logDescription, $logContext);
    }

    protected function log($logLevel, $logDescription, $logContext)
    {
        $this->logLevel = $logLevel;
        $this->logDescription = $logDescription;
        $this->logContext = $logContext ?: [];
        return $this;
    }

    public function getUserMessage()
    {
        return $this->userMessage . json_encode($this->userMessageData, JSON_UNESCAPED_UNICODE);
    }

    public function getDescription()
    {
        return $this->logDescription;
    }

    public function logContext()
    {
        return $this->logContext;
    }


    public function render()
    {
        return response(Api::response(static::API_CODE, $this->userMessage, $this->userMessageData));
    }

    public function report()
    {
        // $user = System::user();
        // $userId = $user->id;
        // $userName = $user->name ?: $user->zh_name;
        // $userMobile = $user->mobile;
        $userId =1;
        $userName="测试数据";
        $userMobile="18010862268";
        
        $path = app()->runningInConsole() ? 'cli' : request()->path();
        $clientIp = app()->runningInConsole() ? '127.0.0.1' : request()->getClientIp();
        $params = app()->runningInConsole() ? '' : json_encode(request()->all());
        Log::{$this->logLevel}(sprintf('%s %s %s %s %s %s %s %s', static::API_CODE, $path, $clientIp, $userId, $userName, $userMobile, $this->logDescription, $params), $this->logContext);
        SystemError::saveNew($this);
        return $this;
    }

    private function __construct(string $message = "", int $code = 0, Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);
    }

}
